namespace SharpF2.Components
{
	using System;
	using System.Runtime.InteropServices;
	using System.Windows;
	using System.Windows.Media;

	/// <summary>
	/// Provides access to the mouse location by calling unmanaged code.
	/// </summary>
	/// <remarks>
	/// This class was written by Dan Crevier (Microsoft).  
	/// http://blogs.msdn.com/llobo/archive/2006/09/06/Scrolling-Scrollviewer-on-Mouse-Drag-at-the-boundaries.aspx.
	/// </remarks>
	public class MouseUtilities
	{
		#region Public Members

		/// <summary>
		/// This method is necessary during 
		/// a drag-drop operation because the WPF mechanisms for retrieving the
		/// cursor coordinates are unreliable.
		/// </summary>
		/// <param name="relativeTo">The Visual to which the mouse coordinates will be relative.</param>
		/// <returns>
		/// Returns the mouse cursor location.
		/// </returns>
		public static Point GetMousePosition(Visual relativeTo)
		{
			var mouse = new Win32Point();
			GetCursorPos(ref mouse);

			// Using PointFromScreen instead of Dan Crevier's code (commented out below)
			// is a bug fix created by William J. Roberts.  Read his comments about the fix
			// here: http://www.codeproject.com/useritems/ListViewDragDropManager.asp?msg=1911611#xx1911611xx
			return relativeTo.PointFromScreen(new Point(mouse.X, mouse.Y));
		}

		#endregion

		#region Private Members

		/// <summary>
		/// Get the position of the cursor
		/// </summary>
		/// <param name="pt">The point of the cursor</param>
		/// <returns>
		/// Return the position of the cursor
		/// </returns>
		[DllImport("user32.dll")]
		private static extern bool GetCursorPos(ref Win32Point pt);

		/// <summary>
		/// Convert a position reference to the screen to the client reference
		/// </summary>
		/// <param name="hwnd">The client handle</param>
		/// <param name="pt">The position cursor</param>
		/// <returns>
		/// Return the position of the cursor in reference of the client
		/// </returns>
		[DllImport("user32.dll")]
		private static extern bool ScreenToClient(IntPtr hwnd, ref Win32Point pt);

		#endregion

		#region Nested type: Win32Point

		/// <summary>
		/// Win32Point structure
		/// </summary>
		[StructLayout(LayoutKind.Sequential)]
		private struct Win32Point
		{
			/// <summary>
			/// The X position
			/// </summary>
			public int X;

			/// <summary>
			/// The Y position
			/// </summary>
			public int Y;
		}

		#endregion
	}
}